import time
import sys
import asyncio

from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget
from PySide6.QtCore import Signal, Slot, QObject

from qasync import QEventLoop, asyncSlot

class WorkerThread(QObject):
    waken = Signal()
    
    def __init__(self):
        super().__init__()
        self.happy_run = True
        
    def run(self):
        print('Task Start')
        while self.happy_run:
            time.sleep(1)
            self.waken.emit()
            print('Task Continue')

    @Slot()
    def try_stop(self):
        self.happy_run = False

class AnimatedLabelDemo(QMainWindow):
    def __init__(self):
        super().__init__()
        self.animation_active = False  # 动画控制标志
        self.current_dots = 0         # 当前显示的点数
        self.run_task = WorkerThread()
        # 信号槽
        self.run_task.waken.connect(self.on_waken)
        self.waken_counter = 0
        self.setup_ui()

    def setup_ui(self):
        """初始化界面组件"""
        self.setWindowTitle("qasync 动画示例")
        self.setGeometry(100, 100, 300, 150)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        layout = QVBoxLayout()
        
        # 显示动画的标签
        self.label = QLabel("准备就绪", self)
        layout.addWidget(self.label)
        
        self.waken_label = QLabel('0', self)
        layout.addWidget(self.waken_label)

        # 任务按钮
        self.btn_start = QPushButton("开始任务", self)
        self.btn_start.clicked.connect(self.on_start_clicked)
        layout.addWidget(self.btn_start)
        
        self.btn_stop = QPushButton("终止任务", self)
        layout.addWidget(self.btn_stop)
        central_widget.setLayout(layout)


    @Slot()
    def on_waken(self):
        self.waken_counter += 1
        self.waken_label.setText(str(self.waken_counter))

    @asyncSlot()
    async def on_start_clicked(self):
        """按钮点击事件处理"""
        self.btn_start.setEnabled(False)
        self.run_task.happy_run = True
        self.btn_stop.clicked.connect(self.run_task.try_stop)
        try:
            # 并行执行动画和耗时任务
            await asyncio.gather(
                self.run_loading_animation(),
                self.run_long_task(),
                asyncio.to_thread(self.run_task.run)
            )
            self.label.setText("任务成功完成!")
        except Exception as e:
            self.label.setText(f"发生错误: {str(e)}")
        finally:
            self.btn_start.setEnabled(True)
            self.animation_active = False

    async def run_loading_animation(self):
        """文字动画效果协程"""
        self.animation_active = True
        self.current_dots = 0
        
        while self.animation_active:
            # 更新标签文本（主线程安全）
            self.label.setText(f"运行中{'.' * self.current_dots}")
            self.current_dots = (self.current_dots + 1) % 4
            
            # 非阻塞等待
            await asyncio.sleep(0.5)

    async def run_long_task(self):
        """模拟耗时任务"""
        try:
            # 模拟分阶段任务
            await asyncio.sleep(1)
            await self.update_status("第一阶段完成")
            
            await asyncio.sleep(1.5)
            await self.update_status("第二阶段进行中...")
            
            await asyncio.sleep(2)
            await self.update_status("最终处理...")
            
            # 模拟可能发生的错误
            raise ValueError("模拟错误")
        finally:
            # 停止动画循环
            self.animation_active = False

    async def update_status(self, text):
        """安全更新状态文本"""
        self.label.setText(f"运行中{'.' * self.current_dots}\n{text}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    
    # 设置 qasync 事件循环
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)
    
    window = AnimatedLabelDemo()
    window.show()

    # 启动事件循环
    with loop:
        sys.exit(loop.run_forever())